﻿/*
 * DatumTransform
 * 
 * initial implementation : 12.07.2011
 *
 * Copyright (c) Adam Sida, asida@centrum.cz.
 * All rights reserved.
 * 
 * for license see Petra.Gis.License.txt
 */
using System;
using System.Collections.Generic;
using Petra.Gis.Geometry.Support;

namespace Petra.Gis.ReferenceSystemServices.Transformations
{

  /// <summary>
  /// implements specific functionality for datum transforms (some syntactic sugar).
  /// Datum transform specific is that single function works for forward and inverse equations
  /// Only transform parameters needs to be inverted during Inverse() call
  /// </summary>
  public abstract class DatumTransform : InversibleParametricTransform
  {

    /// <summary>
    /// local variables for geographic coordinate system angular units
    /// </summary>
    private AngularUnit _srcUnit, _trgtUnit;



    #region constructors


    /// <summary>
    /// xaml constructor
    /// </summary>
    protected DatumTransform()
      :base(){ }




    protected DatumTransform(CoordinateSystem sourceCS,
                            CoordinateSystem targetCS,
                            DistanceUnit distanceParamUnit,
                            AngularUnit angularParamUnit,
                            bool createInverse,
                            TransformParameters parameters
      )
      : base(sourceCS, targetCS, distanceParamUnit, angularParamUnit, createInverse, parameters)
    {
      _srcUnit = (AngularUnit)sourceCS.Unit;
      _trgtUnit = (AngularUnit)targetCS.Unit;

      UpdateTransform();
    }


    #endregion constructors



    #region DatumTransformMembers

    ///// <summary>
    ///// inherited class must implement this method for reverse transform
    ///// Method provides transform for normalized coordinates,
    ///// where coordinate is already converted from coordinate system specific
    ///// units into radians.
    ///// </summary>
    ///// <param name="p"><c>ICoordinate to transform in radians</c></param>
    //protected abstract void inverseTransformN(ICoordinate coord);





    ///// <summary>
    ///// inherited class must implement this method for inverse transform
    ///// Method provides transform for normalized coordinates,
    ///// where coordinate is already converted from coordinate system specific
    ///// units into radians.
    ///// </summary>
    ///// <param name="p"><c>ICoordinate to transform in radians</c></param>
    //protected abstract void forwardTransformN(ICoordinate coord);





    /// <summary>
    /// inherited class must implement this method
    /// Method provides transform for normalized coordinates,
    /// where coordinate is already converted from coordinate system specific
    /// units into radians.
    /// This can be applied for DatumTransform as both coordinate systems are geographics
    /// and uses AngularUnits for coordinates.
    /// </summary>
    /// <param name="p"><c>ICoordinate to transform in radians</c></param>
    protected abstract void transformN(ICoordinate coord);





    protected override void transform(ICoordinate coord)
    {

      if(!IsInverse)
      {
        coord.lon *= _srcUnit.RadiansPerUnit;
        coord.lat *= _srcUnit.RadiansPerUnit;

        transformN(coord);

        coord.lon /= _trgtUnit.RadiansPerUnit;
        coord.lat /= _trgtUnit.RadiansPerUnit;
      }
      else
      {
        coord.lon *= _trgtUnit.RadiansPerUnit;
        coord.lat *= _trgtUnit.RadiansPerUnit;

        transformN(coord);

        coord.lon /= _srcUnit.RadiansPerUnit;
        coord.lat /= _srcUnit.RadiansPerUnit;
      }


    }





    ///// <summary>
    ///// Method provides transformation for <c>CoordinateList</c>.
    ///// Each coordinate is transformed.
    ///// </summary>
    ///// <param name="coordList"></param>
    //public override void Transform(CoordinateList coordList)
    //{

    //  foreach (Coordinate coord in coordList)
    //    this.transform(coord);

    //}




    #endregion DatumTransformMembers
  
  }

}
